package org.study.lucene.api.index;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.*;
import org.apache.lucene.index.*;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.study.lucene.api.constant.PathConstants;

import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

/**
 * 索引基本操作示例
 *
 * @author Administrator
 */
public class IndexCrudDemo {
    public static void main(String[] args) {
        createIndex1();
        // createIndexFormTxt();
    }

    public static void createIndex1() {
        try {
            // 创建 Directory
            Path path1 = Paths.get(PathConstants.INDEX_PATH, new String[0]);
            Path path2 = new File(PathConstants.INDEX_PATH).toPath();
            Directory directory = FSDirectory.open(path1);
            // 在磁盘上创建索引
            Analyzer analyzer = new StandardAnalyzer();
            IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer);
            indexWriterConfig.setOpenMode(IndexWriterConfig.OpenMode.CREATE);
            IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig);
            // 将以下4篇文档添加到本地索引中
            addDocument(indexWriter, "Lucene实战", "193398817");
            addDocument(indexWriter, "Lucene for Dummies", "55320055Z");
            addDocument(indexWriter, "Managing Gigabytes", "55063554A");
            addDocument(indexWriter, "计算机科学的艺术", "9900333X");
            // 关闭资源
            indexWriter.close();
            // 创建查询条件
            String queryStr = "lucene";
            Query query = new QueryParser("title", analyzer).parse(queryStr);
            System.out.println("查询条件：" + query.toString());
            int hitsPerPage = 10;
            // 创建 IndexSearcher
            IndexReader reader = DirectoryReader.open(directory);
            IndexSearcher searcher = new IndexSearcher(reader);
            // 查询
            TopDocs docs = searcher.search(query, hitsPerPage);
            ScoreDoc[] hits = docs.scoreDocs;
            // 结果集
            System.out.println("符合条件的文档数：" + hits.length);
            StoredFields storedFields = searcher.storedFields();
            for (ScoreDoc hit : hits) {
                int docId = hit.doc;
                Document doc = storedFields.document(docId);
                System.out.println(doc.get("title") + " - " + doc.get("isbn"));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    private static void addDocument(IndexWriter writer, String title, String isbn) throws IOException {
        // 创建文档
        Document doc = new Document();
        // 向文档中添加域
        doc.add(new TextField("title", title, Field.Store.YES));
        doc.add(new StringField("isbn", isbn, Field.Store.YES));
        // 将文档添加到本地索引中
        writer.addDocument(doc);
    }

    public static void createIndexFormTxt() {
        try {
            Directory directory = FSDirectory.open(new File(PathConstants.INDEX_PATH).toPath());
            // 在磁盘上创建索引
            Analyzer analyzer = new StandardAnalyzer();
            IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer);
            indexWriterConfig.setOpenMode(IndexWriterConfig.OpenMode.CREATE);
            IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig);
            // 清空索引
            indexWriter.deleteAll();
            List<File> txtFileList = getTxtFileList(PathConstants.DATA_PATH);
            Document document = null;
            for (File file : txtFileList) {
                document = file2Document(file);
                indexWriter.addDocument(document);
            }
            indexWriter.commit();
            indexWriter.close();
            // 创建查询条件
            String queryStr = "山";
            Query query = new QueryParser("content", analyzer).parse(queryStr);
            System.out.println("查询条件：" + query.toString());
            int hitsPerPage = 10;
            // 创建 IndexSearcher
            IndexReader reader = DirectoryReader.open(directory);
            IndexSearcher searcher = new IndexSearcher(reader);
            // 查询
            TopDocs docs = searcher.search(query, hitsPerPage);
            ScoreDoc[] hits = docs.scoreDocs;
            // 结果集
            System.out.println("符合条件的文档数：" + hits.length);
            StoredFields storedFields = searcher.storedFields();
            for (ScoreDoc hit : hits) {
                int docId = hit.doc;
                Document doc = storedFields.document(docId);
                System.out.println(doc.get("filename") + " - " + doc.get("content") + " - " + doc.get("size"));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void updateIndex() {

    }

    public static void queryIndex() {

    }

    public static void deleteIndex() {

    }

    /**
     * 获取指定目录下所有的 txt 文件
     *
     * @param dirPath
     * @return
     */
    public static List<File> getTxtFileList(String dirPath) {
        File[] files = new File(dirPath).listFiles();
        List<File> fileList = new ArrayList<>();
        for (File file : files) {
            if (file.getName().endsWith(".txt")) {
                fileList.add(file);
            }
        }
        return fileList;
    }

    /**
     * 将文件转换成 Document 对象
     *
     * @param file
     * @return
     * @throws Exception
     */
    public static Document file2Document(File file) throws Exception {
        Document document = new Document();
        document.add(new Field("filename", file.getName(), TextField.TYPE_STORED));
        document.add(new Field("content", readFileContent(file), TextField.TYPE_STORED));
        document.add(new Field("size", file.getTotalSpace() + "", TextField.TYPE_STORED));
        return document;
    }

    /**
     * 读取文件内容
     *
     * @param file
     * @return
     * @throws Exception
     */
    public static String readFileContent(File file) throws Exception {
        try (InputStreamReader reader = new InputStreamReader(new FileInputStream(file), "UTF-8");
             BufferedReader br = new BufferedReader(reader);) {
            StringBuilder result = new StringBuilder();
            String lineTxt = null;
            while ((lineTxt = br.readLine()) != null) {
                result.append(lineTxt);
            }
            return result.toString();
        }
    }
}
